package com.rfid.project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import biz.util.*;

import com.rfid.project.model.*;
import com.rfid.project.dao.*;
import com.rfid.project.exception.CannotDelException;
import com.mysema.query.BooleanBuilder;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class ProjectMilestoneService {

	@Autowired
	private ProjectMilestoneDao projectMilestoneDao;

	private QProjectMilestone $ = QProjectMilestone.projectMilestone;

	@Autowired
	public void setProjectMilestoneDao(ProjectMilestoneDao projectMilestoneDao) {
		this.projectMilestoneDao = projectMilestoneDao;
	}

	@Autowired
	private ProjectMilestoneChangeDao projectMilestoneChangeDao;
	
	private QProjectMilestoneChange $_projectMilestoneChange = QProjectMilestoneChange.projectMilestoneChange;
	
	@Autowired
	public void setProjectMilestoneChangeDao(ProjectMilestoneChangeDao projectMilestoneChangeDao) {
		this.projectMilestoneChangeDao = projectMilestoneChangeDao;
	}

	@Autowired
	private ProjectMilestoneFinishApplyDao projectMilestoneFinishApplyDao;
	
	private QProjectMilestoneFinishApply $_projectMilestoneFinish = QProjectMilestoneFinishApply.projectMilestoneFinishApply;
	
	@Autowired
	public void setProjectMilestoneFinishApplyDao(ProjectMilestoneFinishApplyDao projectMilestoneFinishApplyDao) {
		this.projectMilestoneFinishApplyDao = projectMilestoneFinishApplyDao;
	}

	public List<ProjectMilestone> findAll() {
		return ListUtil.toList(projectMilestoneDao.findAll());
	}

	public List<ProjectMilestone> findAllByProject(Project project) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.project.id.eq(project.getId()));
		return ListUtil.toList(projectMilestoneDao.findAll(condition));
	}

	public List<ProjectMilestone> findAll(Long projectId, String name,
			String deliveryDescription, Date firstPlanFinishDateBegin,
			Date firstPlanFinishDateEnd, Date planFinishDateBegin,
			Date planFinishDateEnd, Date actualFinishDateBegin,
			Date actualFinishDateEnd,
			String qualityCheckSign, String status, String remark,
			String orderByAttribute) {
		BooleanBuilder condition = new BooleanBuilder();

		if (IdUtil.isNotEmpty(projectId)) {
			condition.and($.project.id.eq(projectId));
		}

		if (StringUtil.isNotEmpty(name)) {
			condition.and($.name.contains(name));
		}

		if (StringUtil.isNotEmpty(deliveryDescription)) {
			condition.and($.deliveryDescription.contains(deliveryDescription));
		}

		if (firstPlanFinishDateBegin != null) {
			condition
					.and($.firstPlanFinishDate.after(firstPlanFinishDateBegin));
		}

		if (firstPlanFinishDateEnd != null) {
			condition.and($.firstPlanFinishDate.before(firstPlanFinishDateEnd));
		}

		if (planFinishDateBegin != null) {
			condition.and($.planFinishDate.after(planFinishDateBegin));
		}

		if (planFinishDateEnd != null) {
			condition.and($.planFinishDate.before(planFinishDateEnd));
		}

		if (actualFinishDateBegin != null) {
			condition.and($.actualFinishDate.after(actualFinishDateBegin));
		}

		if (actualFinishDateEnd != null) {
			condition.and($.actualFinishDate.before(actualFinishDateEnd));
		}

		if (StringUtil.isNotEmpty(qualityCheckSign)) {
			condition.and($.qualityCheckSign.contains(qualityCheckSign));
		}

		if (StringUtil.isNotEmpty(status)) {
			condition.and($.status.contains(status));
		}

		if (StringUtil.isNotEmpty(remark)) {
			condition.and($.remark.contains(remark));
		}

		return ListUtil.toList(projectMilestoneDao.findAll(condition));
	}

	public Page<ProjectMilestone> findAll(Long projectId, String name,
			String deliveryDescription, Date firstPlanFinishDateBegin,
			Date firstPlanFinishDateEnd, Date planFinishDateBegin,
			Date planFinishDateEnd, Date actualFinishDateBegin,
			Date actualFinishDateEnd,
			String qualityCheckSign, String status, String remark,
			int pageNumber, int pageSize, String sortAttribute,
			String orderDirection) {
		BooleanBuilder condition = new BooleanBuilder();

		if (IdUtil.isNotEmpty(projectId)) {
			condition.and($.project.id.eq(projectId));
		}
		if (StringUtil.isNotEmpty(name)) {
			condition.and($.name.contains(name));
		}
		if (StringUtil.isNotEmpty(deliveryDescription)) {
			condition.and($.deliveryDescription.contains(deliveryDescription));
		}
		if (firstPlanFinishDateBegin != null) {
			condition
					.and($.firstPlanFinishDate.after(firstPlanFinishDateBegin));
		}

		if (firstPlanFinishDateEnd != null) {
			condition.and($.firstPlanFinishDate.before(firstPlanFinishDateEnd));
		}
		if (planFinishDateBegin != null) {
			condition.and($.planFinishDate.after(planFinishDateBegin));
		}

		if (planFinishDateEnd != null) {
			condition.and($.planFinishDate.before(planFinishDateEnd));
		}
		if (actualFinishDateBegin != null) {
			condition.and($.actualFinishDate.after(actualFinishDateBegin));
		}

		if (actualFinishDateEnd != null) {
			condition.and($.actualFinishDate.before(actualFinishDateEnd));
		}
		if (StringUtil.isNotEmpty(qualityCheckSign)) {
			condition.and($.qualityCheckSign.contains(qualityCheckSign));
		}
		
		if (StringUtil.isNotEmpty(status)) {
			condition.and($.status.contains(status));
		}
		if (StringUtil.isNotEmpty(remark)) {
			condition.and($.remark.contains(remark));
		}

		Sort sortObject = null;
		if (StringUtil.isEmpty(sortAttribute)) {
			sortObject = new Sort(Direction.DESC, "id");
		} else {
			sortObject = new Sort(Direction.fromStringOrNull(orderDirection),
					sortAttribute);
		}

		PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize,
				sortObject);
		return projectMilestoneDao.findAll(condition, pageRequest);
	}

	public ProjectMilestone getProjectMilestone(Long id) {
		return projectMilestoneDao.getOne(id);
	}

	public void deleteProjectMilestone(Long id) throws CannotDelException {
		if (this.findProjectMilestoneChangeByProjectMilestone(id)) {
			throw new CannotDelException("有项目节点变更引用此项目节点，无法删除！");
		} else if(this.findProjectMilestoneFinishApplyByProjectMilestone(id)){
			throw new CannotDelException("有项目节点完成申请引用此项目节点，无法删除！");
		} else {
			projectMilestoneDao.delete(id);
		}
	}
	
	private boolean findProjectMilestoneChangeByProjectMilestone(Long projectMilestoneId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_projectMilestoneChange.projectMilestone.id.eq(projectMilestoneId));
		return this.projectMilestoneChangeDao.count(condition) > 0;
	}
	
	private boolean findProjectMilestoneFinishApplyByProjectMilestone(Long projectMilestoneId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_projectMilestoneFinish.projectMilestone.id.eq(projectMilestoneId));
		return this.projectMilestoneFinishApplyDao.count(condition) > 0;
	}

	public void saveProjectMilestone(ProjectMilestone projectMilestone) {
		if (null == projectMilestone.getPlanReviseCount()) {
			projectMilestone.setPlanReviseCount(0);
		}
		if(projectMilestone.getFirstPlanFinishDate() != projectMilestone.getPlanFinishDate()){
			projectMilestone.setPlanFinishDate(projectMilestone.getFirstPlanFinishDate());
		}
		projectMilestoneDao.save(projectMilestone);
	}
	
	public Set<Project> findQualityCheckSignProjects(String qualityCheckSign){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$.qualityCheckSign.eq(qualityCheckSign));
		List<ProjectMilestone> projectMilestones = ListUtil.toList(this.projectMilestoneDao.findAll(condition));
		Set<Project> projects = new HashSet<Project>();
		for (ProjectMilestone projectMilestone : projectMilestones) {
			projects.add(projectMilestone.getProject());
		}
		return projects;
	}

	public void editProjectMilestoneQualityCheck(ProjectMilestone projectMilestone) {
		ProjectMilestone sourceProjectMilestone = this.projectMilestoneDao.findOne(projectMilestone.getId());
		sourceProjectMilestone.setRemark(projectMilestone.getRemark());
		
		this.projectMilestoneDao.save(sourceProjectMilestone);
	}

	public void pullDownProjectMilestone(ProjectMilestone projectMilestone) {
		ProjectMilestone sourceProjectMilestone = this.projectMilestoneDao.findOne(projectMilestone.getId());
		sourceProjectMilestone.setStatus(projectMilestone.getStatus());
		this.projectMilestoneDao.save(sourceProjectMilestone);
	}

	public ProjectMilestone findOne(Long id) {
		return this.projectMilestoneDao.findOne(id);
	}

	public ProjectMilestone findAll(Long id) {
		return this.projectMilestoneDao.findOne(id);
	}

}
